#!/usr/bin/python

gen = 0x04c11db7
explist = []

for i in range(8):              # 0 .. 7
    byte = ((gen<<(7-i)) | (gen>>(25+i))) & 0xff
    # print("CrcNext[%d] = Crc[%d] " % (i, i-8))
    expression = "Crc[%d]" % (32+i-8)
    for j in range(8):
        if byte & 0x1 :
            if j==7-i : 
                expression += " ^ D[%d]" % j
            else:
                expression += " ^ F[%d]" % j
        byte >>= 1
    explist.append(expression)
    # print("CrcNext[%d] = %s" % (i, expression))


for i in range(8, 32):
    byte = (gen>>(i-7)) & 0xff
    # print("CrcNext[%d] = Crc[%d] " % (i, i-8))
    expression = "Crc[%d]" % (i-8)
    for j in range(8):
        if byte & 0x1 :
            expression += " ^ F[%d]" % j
        byte >>= 1
    explist.append(expression)
    # print("CrcNext[%d] = %s" % (i, expression))
        
replace_exp = [
    ["F[0]", "D[0] ^ Crc[31]"],
    ["F[1]", "D[1] ^ Crc[30]"],
    ["F[2]", "D[2] ^ Crc[29]"],
    ["F[3]", "D[3] ^ Crc[28]"],
    ["F[4]", "D[4] ^ Crc[27]"],
    ["F[5]", "D[5] ^ Crc[26]"],
    # ["F[6]", "D[6] ^ F[0] ^ Crc[25]"],
    ["F[6]", "D[6] ^ D[0] ^ Crc[31] ^ Crc[25]"],
    # ["F[7]", "D[7] ^ F[1] ^ Crc[24]"] ];
    ["F[7]", "D[7] ^ D[1] ^ Crc[30] ^ Crc[24]"] ];

print("original expression:")
for i,e in enumerate(explist):
    print("CrcNext[%d] = %s" % (i, e))
print("="*100)    

for i,exp in enumerate(explist):
    # first replace the F[i]
    for r in replace_exp:
        exp = exp.replace(r[0], r[1])
    # simplify the expression
    vars = exp.split("^")
    vars = [j.strip() for j in vars]
    vars.sort()
    # print(vars)
    factor_list = []
    while len(vars) > 0:
        factor = vars.pop()
        n = vars.count(factor)
        if n%2 == 0:
            factor_list.append(factor)
        for j in range(n):
            vars.remove(factor)
    # print(factor_list)
    # print("assign CrcNext[%d] = %s;" % (i, " ^ ".join(factor_list).replace("D[", "Data[")))
    # print("assign CrcNext[%d] = enable & (%s);" % (i, " ^ ".join(factor_list).replace("D[", "Data[")))

    # when enable is 0, the CRC regs only shift left for 8bits each clk (the low 8 bits clear to 0)
    if i<=7:
        print("assign CrcNext[%d] = enable & (%s);" % (i, " ^ ".join(factor_list).replace("D[", "Data[")))
    else:
        ori_str = "Crc[%d]" % (i-8)
        factor_list.remove(ori_str);
        # print("%s" % ori_str , factor_list)
        print("assign CrcNext[%d] = (enable & (%s)) ^ %s;" % (i, " ^ ".join(factor_list).replace("D[", "Data["), ori_str))
            
    

# for i in explist:
#     print(i)
